home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------
-
- C source for XWindShell XCMD
-
- Copyright © 1989-92 Apple Computer, Inc.
-
-
- This file includes the source code for the XWindShell XCMD. While
- this XCMD will compile and execute in its current form. The XWindow
- has no functionality beyond demonstrating the basics of HyperCard's
- XWindow capabilities. This file is meant to be a basis where an
- XCMD author can "fill in the blanks" to create their XCMD. See the
- other sample XCMDs such as Picture, MemState, and ListWindow for
- practical examples of code dealing with responding to XWindow events
- and strategies for storing information for the XWindows while they
- are open.
-
- The files included with the XWindShell XCMD are meant to be
- used as a starting point for XCMDs in C or Pascal that wish to
- create and manage XWindows.
-
- Files:
- ------
- *XWindShell.c
- XWindShell.r
- MakeFile
-
-
- Author: Darin Acquistapace
- Created: 01/29/92
- Modified: See Mod History Below
-
- Modification History:
- ---------------------
- 01/29/92 - New today.
-
- ------------------------------------------------------------------ */
-
- #include <Types.h>
- #include <Memory.h>
- #include <MiscTool.h>
- #include <GSOS.h>
- #include <QuickDraw.h>
- #include <Resources.h>
- #include <QDAux.h>
- #include <Event.h>
- #include <Control.h>
- #include <Windows.h>
- #include <HyperXCMD.h>
-
- /* Define any global variables here. The makeFile instructs the linker
- to link this segment after EntrySeg and Main. */
- Word memoryID;
- XCMDPtr gParamPtr;
-
- /* Forward declarations */
- void CleanUpMemory();
- Boolean CorrectVersion();
- void HandleCursorWithin();
- void HandleEvents();
- void HandleHideShow();
- void HandleOpenEvent();
- void HandleWindowClick();
- void HTError();
- void MyDisposeHandle();
- void ProcessIdle();
- void ReturnResult();
- void SetUpContents();
- void UpdateXWindow();
- pascal void XWindShell();
-
- /* The first segment in the XCMD, calls the main routine. */
- segment "EntrySeg";
- pascal void EntryPoint(paramPtr)
- XCMDPtr paramPtr;
- {
- XWindShell(paramPtr);
- } /* EntryPoint */
-
- /* The Main segment. This is placed immediately after EntrySeg in the XCMD. */
- segment "Main";
- pascal void XWindShell(paramPtr)
- XCMDPtr paramPtr;
- {
- /* The main routine of the XCMD. Most XWindow XCMDs will have a fairly small
- main routine with the majority of the bulk of the XCMD in the routines
- dispatched to by the HandleEvents procedure. This main routine simply
- deals with calling HandleEvents, displaying Help or Copyright notices,
- and the initial creation of the XWindow. */
-
- #define kLeftPos 100 /* Window coordinates in 640 coordinates */
- #define kTopPos 50
- #define kWindWidth 250
- #define kWindHeight 60
-
- int pCount;
- WindowPtr xWindow;
- Rect windRect;
-
- char *copyrightStr = "\pAnswer \"XWindShell XCMD v1.0\" & return & \"by Darin Acquistapace, 1/29/92\" & return & \"© 1992 Apple Computer, Inc.\"";
- char *helpStr = "\pAnswer \"FORM: XWindShell\"";
- char *wrongVersionStr = "\pXWindShell XCMD requires HyperCard IIGS 1.1";
- char *createErrStr = "\pUnable to create window";
- char *windTitle = "\pSampleXWindow";
-
- Str255 str;
-
- /* Get the memory ID to be used for all calls to the memory manager. This
- ID will be unique to _each_ XWindow. */
- memoryID = paramPtr->userID;
- pCount = paramPtr->paramCount;
- gParamPtr = paramPtr;
-
- /* If the paramCount is negative, we have been called in response to an event. */
- if (pCount < 0) {
- HandleEvents();
- return;
- }
-
- /* Display help or copyright info in response to "?" or "!". */
- if (pCount == 1) {
- ZeroToPas(*(paramPtr->params[0]), &str);
- if (str.text[0] == '!') {
- SendHCMessage(copyrightStr);
- return;
- }
- if (str.text[0] == '?') {
- SendHCMessage(helpStr);
- return;
- }
- }
-
- /* Make sure we are running at least version 1.1 of HyperCard IIGS. */
- if (! CorrectVersion()) {
- ReturnResult(wrongVersionStr);
- return;
- }
-
- /* Check for the desired number of parameters. XCMDs with optional
- parameters will need to check the paramCount for being within a
- certain range. Only scripting errors such as an invalid paramCount
- should generate a HyperTalk error. Other problems such as invalid or
- out-of-range data in the parameters should be handled by returning an
- appropriate error string the the result. */
- if (pCount != 0) {
- HTError();
- return;
- }
-
- /* Here the XCMD should process any parameters required. See the other
- sample XCMDs for examples of using the ZeroToPas and other conversion
- callbacks to convert the zero-terminated input parameters into other
- forms. */
-
- /* Create the XWindow invisible. We'll show it after we perform any
- needed initialization on it, such as creating controls, etc. */
- SetRect(&windRect, kLeftPos, kTopPos, kLeftPos + kWindWidth, kTopPos + kWindHeight);
- xWindow = NewXWindow(&windRect, windTitle, false, xWindoidStyle);
- if (xWindow == nil) {
- ReturnResult(createErrStr);
- return;
- }
-
- /* Create the contents for the window */
- SetPort(xWindow);
- SetUpContents(xWindow);
-
- /* Display the window. This will generate an update event which will be sent
- immediately following the xOpenEvt. */
- ShowWindow(xWindow);
- } /* XWindShell */
-
-
- /* -------------------------------------------------------------------------- */
- void ReturnResult(str)
- /* Puts the specified string into the result and terminates. */
- Str255 *str;
- {
- gParamPtr->returnValue = PasToZero(str);
- } /* ReturnResult */
-
-
- /* -------------------------------------------------------------------------- */
- void HTError()
- /* Generates a HyperTalk error dialog box complete with Script and Cancel
- buttons. */
- {
- char *ScriptErrStr = "\pCan't understand arguments of XCMD XWindShell.";
-
- gParamPtr->returnStat = 1;
- ReturnResult(ScriptErrStr);
- } /* HTError */
-
-
- /* -------------------------------------------------------------------------- */
- void MyDisposeHandle(h)
- /* Checks a handle for NIL before disposing of it. A good practice. */
- Handle h;
- {
- if (h != nil) DisposeHandle(h);
- } /* MyDisposeHandle */
-
-
- /* -------------------------------------------------------------------------- */
- void CleanUpMemory(whichWindow)
- /* Free all memory associated with the XWindow. This could be a handle
- referenced by the GetXWindowValue callback. */
- WindowPtr whichWindow;
- {
- } /* CleanUpMemory */
-
-
- /* -------------------------------------------------------------------------- */
- void HandleWindowClick(whichWindow, ourEvent)
- /* A mouseDown event has occurred in our window. This procedure handles
- tracking the click and taking whatever actions are necessary as a result
- of the click. Tracking controls in XWindows is no different than doing
- the same in any standard window. FindControl and TrackControl would be
- commonly used to track the click. See the Picture and ListWindow sample
- XCMDs for examples of using the control manager to handle these actions. */
- WindowPtr whichWindow;
- EventRecord ourEvent;
- {
- } /* HandleWindowClick */
-
-
- /* -------------------------------------------------------------------------- */
- void ProcessIdle(whichWindow)
- /* Take any actions that need to be performed periodically. This procedure
- will only be called if the SetXWIdleTime callback has been called with
- an interval value other than zero (the default.) */
- WindowPtr whichWindow;
- {
- } /* ProcessIdle */
-
-
- /* -------------------------------------------------------------------------- */
- void HandleOpenEvent(whichWindow)
- /* Perform any actions necessary before any other events are sent. At this
- point, the window is created and visible. */
- WindowPtr whichWindow;
- {
- /* Allow reentrancy, if this is not set, the XWindow may lose events that
- occur because of events instigated by the XCMD. For instance, if the
- mouseDown handler performs some action which causes HyperCard to close
- the XWindow, the xCloseEvt will not be received because the XCMD has the
- code in the mouseDown handler pending and will be returned to when Hyper-
- Card finishes executing whatever task the mouseDown handler began. This
- can be set to true for both types of events in most XCMDs and set to false
- temporarily if the need arises to temporarily halt recursive calls to the
- XCMD.
-
- If an XCMD wishes to recieve null events, it should call SetXWIdleTime
- at this point with an interval other than zero. */
- XWAllowReEntrancy(whichWindow, true, true);
- } /* HandleOpenEvent */
-
-
- /* -------------------------------------------------------------------------- */
- void HandleCursorWithin(whichWindow, cursorLoc)
- /* The mouse cursor is within the XWindow, perform any actions necessary,
- such as changing the cursor shape. */
- {
- /* Setting the passFlag to true tells HyperCard that we would like it
- to handle changing the cursor to an arrow when the cursor is within
- the XWindow just as it does for the built-in windows. */
- gParamPtr->passFlag = true;
- } /* HandleCursorWithin */
-
-
- /* -------------------------------------------------------------------------- */
- void HandleHideShow(hideFlag)
- /* An XCMD has called either the HideHCPalettes or ShowHCPalettes callbacks
- and our visible status has changed. An XCMD may wish to deallocate memory
- used for updating the XWindow if it knows it will be hidden for a period of
- time. An example usage would be if a significant amount of memory was
- required to maintain the contents of an XWindow. A script could call an
- XCMD to send the HidePalettes event when the user entered the paint tools
- so that the XCMD could free what memory it could to provide more memory
- for the paint buffers. */
- Boolean hideFlag;
- {
- } /* HandleHideShow */
-
-
- /* -------------------------------------------------------------------------- */
- void HandleEvents()
- /* Handle events specific to our XWindow. HyperCard will only send events
- to the XCMD pertaining to windows it has opened. The XCMD, however,
- should not assume that it owns only one window. Subsequent calls to
- the XCMD to create the XWindow will result in one XCMD code segment
- owning multiple XWindows. This routine is similar to the main event loop
- of an application, all events dealing with the XWindows the XCMD has
- created will be sent here and dispatched to the appropriate routine to
- respond to them. */
- {
- XWEventInfoPtr myEventInfo;
- WindowPtr window;
- EventRecord event;
-
- myEventInfo = (XWEventInfoPtr) gParamPtr->params[0];
- window = myEventInfo->eventWindow;
- event = myEventInfo->event;
-
- switch (event.what) {
- case nullEvt: ProcessIdle(window);
- break;
- case xOpenEvt: HandleOpenEvent(window);
- break;
- case updateEvt: UpdateXWindow(window);
- break;
- case mouseDownEvt: HandleWindowClick(window, event);
- break;
- case xHidePalettesEvt:
- case xShowPalettesEvt: HandleHideShow(event.what == xHidePalettesEvt);
- break;
- case xCloseEvt: CleanUpMemory(window);
- break;
- case xCursorWithin: HandleCursorWithin(window, event.where);
- break;
- }
- } /* HandleEvents */
-
-
- /* -------------------------------------------------------------------------- */
- void SetUpContents(whichWindow)
- /* Our window has been created via a call to the NewXWindow callback and is
- invisible. Now handle any initialization necessary for the XWindow such as
- calling NewControl, etc. */
- WindowPtr whichWindow;
- {
- } /* SetUpContents */
-
-
- /* -------------------------------------------------------------------------- */
- void UpdateXWindow(whichWindow)
- /* Handles updating the contents of the XWindow. This may include drawing
- a background picture, calling DrawControls, etc. HyperCard takes care of
- calling BeginUpdate and EndUpdate for you. This routine should only update
- the window. Be careful not to do anything that might cause another update
- event to occur which would result in recursion. */
- WindowPtr whichWindow;
- {
- } /* UpdateXWindow */
-
-
- /* -------------------------------------------------------------------------- */
- Boolean CorrectVersion()
- /* Returns true if the version of HyperCard IIGS currently running is greater
- than or equal to the string "1.1". Note that we're performing the check
- by simply checking the first digit after the decimal point. This is
- reasonable since the only value that should fail is zero. */
- {
- Handle tempHandle;
- Str255 tempStr;
-
- tempHandle = EvalExpr("\pthe version");
- ZeroToPas(*tempHandle, &tempStr);
- MyDisposeHandle(tempHandle);
- return ( (byte) tempStr.text[2] >= 49);
-
- }